package com.cz.datafetcher.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cz.datafetcher.common.ForginColumn;
import com.cz.datafetcher.common.ReflectionUtils;
import com.cz.datafetcher.dao.SuperMapper;
import com.cz.datafetcher.entity.search.BaseSearchModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


public abstract class SingleTabWithForginControllerBase
        <TObj, Key extends Serializable, Service extends IService<TObj>,Search extends BaseSearchModel>
    extends SingleTabControllerBase<TObj, Key, Service,Search>
{
    @Autowired
    private SuperMapper superMapper;


    @Override
    @PostMapping("/search")
    public IPage<TObj> Search(@RequestBody Search search) {
        Type modelType = ReflectionUtils.getGenericParameterType(getClass(), 0);
        HashMap<Field, ForginColumn> map = getForginColumns((Class) modelType);

        IPage<TObj> search1 = super.Search(search);
        List<TObj> records = search1.getRecords();

        for (Field field : map.keySet()) {
            String join = getSearchidsString(records, field);

            ForginColumn forginColumn = map.get(field);
            if(StringUtils.isBlank(forginColumn.setClassField())) continue;
            Field nameField = null;
            try {
                nameField = ((Class) modelType).getDeclaredField(forginColumn.setClassField());

            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
            if(nameField==null) {
                //System.out.println("namefield is null");
                continue;
            }
            nameField.setAccessible(true);
            Field finalNameField = nameField;

            List<Map<String, Object>> maps = getDataFromDb(join, forginColumn);

            setNameFieldValue(records, field, forginColumn, finalNameField, maps);
        }

        return search1;
    }

    private void setNameFieldValue(List<TObj> records, Field forginField, ForginColumn forginColumn, Field nameField, List<Map<String, Object>> maps) {
        for (TObj record : records) {
            try {
                Object o = forginField.get(record);
                if(o==null) continue;
                for (Map<String, Object> map : maps) {
                    Object id = map.get(forginColumn.primaryKeyColumn());
                    if(id==null) continue;
                    //System.out.println(forginField.getName()+","+nameField.getName());
                    //System.out.println("o="+o+",id="+id);
                    //System.out.println("==?"+o.toString().equals(id.toString()));
                    if(o.toString().equals(id.toString())){
                        Object shownameStr = map.get(forginColumn.showColumn());
                        nameField.set(record,shownameStr);
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }


        }
    }

    private List<Map<String, Object>> getDataFromDb(String join, ForginColumn forginColumn) {
        String sql = String.format("select %s,%s from %s where %s in (%s)", forginColumn.primaryKeyColumn(), forginColumn.showColumn(), forginColumn.table(), forginColumn.primaryKeyColumn(), join);
        //System.out.println(sql);
        List<Map<String, Object>> maps = superMapper.RunSql(sql);
        //System.out.println(maps);
        return maps;
    }

    private String getSearchidsString(List<TObj> records, Field field) {
        List<Object> collect = records.stream().map(x -> {
            Object o = null;
            try {
                o = field.get(x);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return o;
        }).filter(x -> x != null).collect(Collectors.toList());
        //System.out.println(collect.size());
        String join = StringUtils.join(collect, ",");
        return join;
    }

    private HashMap<Field, ForginColumn> getForginColumns(Class modelType) {
        Field[] fields = modelType.getDeclaredFields();
        HashMap<Field, ForginColumn> map = new HashMap<>();
        for (Field field : fields) {
            ForginColumn annotation = field.getAnnotation(ForginColumn.class);
            if(annotation!=null){
                field.setAccessible(true);
                map.put(field,annotation);
            }
        }
        return map;
    }


}
